local foecount = 0
local foesbeat = 0
local ringcount = 0
local ringscollected = 0

--function for Rayman font

local function intToHud(v, x, y, el, f)
	if el == 0
		v.draw(x, y, v.cachePatch("RAYHDNO0"), V_HUDTRANS|V_PERPLAYER|f)
	else
		local offset = 0
		while el ~= 0
			v.draw(x + offset, y, v.cachePatch("RAYHDNO" + el % 10), V_HUDTRANS|V_PERPLAYER|f)
			el = $ / 10
			offset = $ - 12
		end
	end
end

--Score overhaul
local enemycount = 0
local enemydestroyed = 0
local ringcount = 0
local ringcollect = 0
local zeroerror = 0

--Constants for emblems
--Global
local GLOBAL_ZERO_SCORE_EMBLEM = 100
local MAX_RINGS_EMBLEM = 101
local MAX_ENEMIES_EMBLEM = 102

local score = 0
local basescore = 0
local drawtimebonus = 0
local drawringbonus = 0
local timebonus = 0
local ringbonus = 0
local playerscore = 0

local function doRingValue(val)
	return val
end

--Yellow Lums

local lums = 0
local lumattack = 0
local maxlums = 0
local lumarray = {}
local LUMS_EMBLEM = 50
local LUMS_TIME_EMBLEM = 51
local currentlumid = 1

local lumfile = "client/lumdata/"
local file
local fileupdateflag = 0
local lumprogress = ""

local previousMap

local closestlum
local closestdist

--Yellow Lums

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_YELLOWLUM_2)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_YELLOWLUM)

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_YELLOWLUM_3)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_YELLOWLUM_2)

addHook("MobjSpawn", function(mobj)
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_YELLOWLUM_3)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
end, MT_RAYMAN_YELLOWLUM_2)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
end, MT_RAYMAN_YELLOWLUM_3)

addHook("MobjDeath", function(mobj)
	local sparkcount = P_RandomRange(8, 10)
	for i = 1, sparkcount do
		local spark = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_YELLOWLUM_SPARK)
		spark.momx = P_RandomRange(-8, 8) * FRACUNIT
		spark.momy = P_RandomRange(-8, 8) * FRACUNIT
		spark.momz = P_RandomRange(0, 12) * FRACUNIT
	end
end, MT_RAYMAN_YELLOWLUM)

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_YELLOWLUM_SPARK_2)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_YELLOWLUM_SPARK)

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_YELLOWLUM_SPARK_3)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_YELLOWLUM_SPARK_2)

addHook("MobjSpawn", function(mobj)
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_YELLOWLUM_SPARK_3)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
	mobj.momx = mobj.target.momx
	mobj.momy = mobj.target.momy
	mobj.momz = mobj.target.momz
end, MT_RAYMAN_YELLOWLUM_SPARK_2)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
	mobj.momx = mobj.target.momx
	mobj.momy = mobj.target.momy
	mobj.momz = mobj.target.momz
end, MT_RAYMAN_YELLOWLUM_SPARK_3)

--White Lums

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_WHITELUM_2)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_WHITELUM)

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_WHITELUM_3)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_WHITELUM_2)

addHook("MobjSpawn", function(mobj)
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_WHITELUM_3)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
end, MT_RAYMAN_WHITELUM_2)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
end, MT_RAYMAN_WHITELUM_3)

addHook("MobjDeath", function(mobj)
	local sparkcount = P_RandomRange(8, 10)
	for i = 1, sparkcount do
		local spark = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_WHITELUM_SPARK)
		spark.momx = P_RandomRange(-8, 8) * FRACUNIT
		spark.momy = P_RandomRange(-8, 8) * FRACUNIT
		spark.momz = P_RandomRange(0, 12) * FRACUNIT
	end
end, MT_RAYMAN_WHITELUM)

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_WHITELUM_SPARK_2)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_WHITELUM_SPARK)

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_WHITELUM_SPARK_3)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_WHITELUM_SPARK_2)

addHook("MobjSpawn", function(mobj)
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_WHITELUM_SPARK_3)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
	mobj.momx = mobj.target.momx
	mobj.momy = mobj.target.momy
	mobj.momz = mobj.target.momz
end, MT_RAYMAN_WHITELUM_SPARK_2)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
	mobj.momx = mobj.target.momx
	mobj.momy = mobj.target.momy
	mobj.momz = mobj.target.momz
end, MT_RAYMAN_WHITELUM_SPARK_3)

--Red Lums

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_REDLUM_2)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
	mobj.spawntimer = 8
end, MT_RAYMAN_REDLUM)

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_REDLUM_3)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_REDLUM_2)

addHook("MobjSpawn", function(mobj)
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_REDLUM_3)

addHook("MobjThinker", function(mobj)
	if mobj.spawntimer > 0
		mobj.spawntimer = $ - 1
		if mobj.spawnpoint then return end
		mobj.momz = 2 * FRACUNIT
	else
		mobj.momz = 0
	end
end, MT_RAYMAN_REDLUM)

addHook("TouchSpecial", function(mobj, toucher)
	if toucher ~= nil
	and toucher.player ~= nil
	and toucher.player.bot == 0
		if mobj.spawntimer > 0 then return true end
	end
end, MT_RAYMAN_REDLUM)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
end, MT_RAYMAN_REDLUM_2)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
end, MT_RAYMAN_REDLUM_3)

addHook("MobjDeath", function(mobj)
	local sparkcount = P_RandomRange(8, 10)
	for i = 1, sparkcount do
		local spark = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_REDLUM_SPARK)
		spark.momx = P_RandomRange(-8, 8) * FRACUNIT
		spark.momy = P_RandomRange(-8, 8) * FRACUNIT
		spark.momz = P_RandomRange(0, 12) * FRACUNIT
	end
end, MT_RAYMAN_REDLUM)

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_REDLUM_SPARK_2)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_REDLUM_SPARK)

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_REDLUM_SPARK_3)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_REDLUM_SPARK_2)

addHook("MobjSpawn", function(mobj)
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_REDLUM_SPARK_3)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
	mobj.momx = mobj.target.momx
	mobj.momy = mobj.target.momy
	mobj.momz = mobj.target.momz
end, MT_RAYMAN_REDLUM_SPARK_2)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
	mobj.momx = mobj.target.momx
	mobj.momy = mobj.target.momy
	mobj.momz = mobj.target.momz
end, MT_RAYMAN_REDLUM_SPARK_3)

addHook("TouchSpecial", function(mobj, toucher)
	if toucher ~= nil
	and toucher.player ~= nil
	and toucher.player.bot == 0
		if mobj.spawntimer > 0 then return end
		P_AddPlayerScore(toucher.player, 100)
		if toucher.rayhp < 5
			toucher.rayhp = $ + 1
			return
		end
		P_AddPlayerScore(toucher.player, 100)
	end
end, MT_RAYMAN_REDLUM)

--Blue Lums

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_BLUELUM_2)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_BLUELUM)

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_BLUELUM_3)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_BLUELUM_2)

addHook("MobjSpawn", function(mobj)
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_BLUELUM_3)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
end, MT_RAYMAN_BLUELUM_2)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
end, MT_RAYMAN_BLUELUM_3)

addHook("MobjDeath", function(mobj)
	local sparkcount = P_RandomRange(8, 10)
	for i = 1, sparkcount do
		local spark = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_BLUELUM_SPARK)
		spark.momx = P_RandomRange(-8, 8) * FRACUNIT
		spark.momy = P_RandomRange(-8, 8) * FRACUNIT
		spark.momz = P_RandomRange(0, 8) * FRACUNIT
	end
end, MT_RAYMAN_BLUELUM)

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_BLUELUM_SPARK_2)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_BLUELUM_SPARK)

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_BLUELUM_SPARK_3)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_BLUELUM_SPARK_2)

addHook("MobjSpawn", function(mobj)
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_BLUELUM_SPARK_3)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
	mobj.momx = mobj.target.momx
	mobj.momy = mobj.target.momy
	mobj.momz = mobj.target.momz
end, MT_RAYMAN_BLUELUM_SPARK_2)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
	mobj.momx = mobj.target.momx
	mobj.momy = mobj.target.momy
	mobj.momz = mobj.target.momz
end, MT_RAYMAN_BLUELUM_SPARK_3)

addHook("TouchSpecial", function(mobj, toucher)
	if toucher ~= nil
	and toucher.player ~= nil
	and toucher.player.bot == 0
		if not S_SoundPlaying(mobj, sfx_blulum) then S_StartSound(mobj, sfx_blulum) end
		local score = 100
		if toucher.player.powers[pw_underwater] > 0
			if mobj.spawnpoint.options & 4
			or mobj.spawnpoint.args[0] & 1
				toucher.player.powers[pw_underwater] = $ + 12
			else
				toucher.player.powers[pw_underwater] = $ + underwatertics / 3
			end
			if toucher.player.powers[pw_underwater] > underwatertics
				toucher.player.powers[pw_underwater] = underwatertics
				score = 200
			end
			if toucher.player.powers[pw_underwater] > 11*TICRATE + 1
				P_RestoreMusic(toucher.player)
			end
		end
		if toucher.player.powers[pw_spacetime] > 0
			if mobj.spawnpoint.options & 4
			or mobj.spawnpoint.args[0] & 1
				toucher.player.powers[pw_spacetime] = $ + 12
			else
				toucher.player.powers[pw_spacetime] = $ + spacetimetics / 3
			end
			if toucher.player.powers[pw_spacetime] > spacetimetics
				toucher.player.powers[pw_spacetime] = spacetimetics
				score = 200
			end
		end
		if mobj.spawnpoint.options & 4
		or mobj.spawnpoint.args[0] & 1
			score = 0
			local spark = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_BLUELUM_SPARK)
			spark.momx = P_RandomRange(-8, 8) * FRACUNIT
			spark.momy = P_RandomRange(-8, 8) * FRACUNIT
			spark.momz = P_RandomRange(0, 8) * FRACUNIT
			return true
		else
			S_StartSound(mobj, sfx_yellum)
		end
		P_AddPlayerScore(toucher.player, score)
	end
end, MT_RAYMAN_BLUELUM)


--Green Lums

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_GREENLUM_2)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_GREENLUM)

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_GREENLUM_3)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_GREENLUM_2)

addHook("MobjSpawn", function(mobj)
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_GREENLUM_3)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
end, MT_RAYMAN_GREENLUM_2)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
end, MT_RAYMAN_GREENLUM_3)

addHook("MobjDeath", function(mobj)
	local sparkcount = P_RandomRange(16, 20)
	for i = 1, sparkcount do
		local spark = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_GREENLUM_SPARK)
		spark.momx = P_RandomRange(-8, 8) * FRACUNIT
		spark.momy = P_RandomRange(-8, 8) * FRACUNIT
		spark.momz = P_RandomRange(0, 12) * FRACUNIT
	end
end, MT_RAYMAN_GREENLUM)

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_GREENLUM_SPARK_2)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_GREENLUM_SPARK)

addHook("MobjSpawn", function(mobj)
	local bright = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_GREENLUM_SPARK_3)
	bright.target = mobj
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_GREENLUM_SPARK_2)

addHook("MobjSpawn", function(mobj)
	mobj.renderflags = $ + RF_NOCOLORMAPS
end, MT_RAYMAN_GREENLUM_SPARK_3)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
	mobj.momx = mobj.target.momx
	mobj.momy = mobj.target.momy
	mobj.momz = mobj.target.momz
end, MT_RAYMAN_GREENLUM_SPARK_2)

addHook("MobjThinker", function(mobj)
	if mobj.target == nil then P_RemoveMobj(mobj) return end
	P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z)
	mobj.momx = mobj.target.momx
	mobj.momy = mobj.target.momy
	mobj.momz = mobj.target.momz
end, MT_RAYMAN_GREENLUM_SPARK_3)

addHook("TouchSpecial", function(mobj, toucher)
	if toucher ~= nil
	and toucher.player ~= nil
	and toucher.player.bot == 0
		toucher.player.starpostx = mobj.x / FRACUNIT
		toucher.player.starposty = mobj.y / FRACUNIT
		toucher.player.starpostz = mobj.z / FRACUNIT - 24
		toucher.player.starpostangle = mobj.angle
		toucher.player.starpostscale = toucher.scale
		if multiplayer
			local spark = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_GREENLUM_SPARK)
			spark.momx = P_RandomRange(-8, 8) * FRACUNIT
			spark.momy = P_RandomRange(-8, 8) * FRACUNIT
			spark.momz = P_RandomRange(0, 12) * FRACUNIT
			return true
		end
		P_AddPlayerScore(toucher.player, 1000)
	end
end, MT_RAYMAN_GREENLUM)

addHook("PlayerSpawn", function(player)
	if not mapheaderinfo[gamemap].scorehaullua then return end
	if not multiplayer
		ringcollect = 0
		enemydestroyed = 0
	end
	player.spawnscore = player.score
	player.mo.rayhp = 5
	if player.starposttime == 0
		player.starpostx = player.mo.x / FRACUNIT
		player.starposty = player.mo.y / FRACUNIT
		player.starpostz = player.mo.z / FRACUNIT
		player.starpostangle = player.mo.angle
		player.starpostscale = player.mo.scale
	end
end)

--Award emblems

addHook("PlayerThink", function(player)
	if not mapheaderinfo[gamemap].lumslua then return end
	
	if player.bot ~= 0 then return end
	
	hud.disable("score")
	hud.disable("time")
	hud.disable("rings")
	hud.disable("lives")
	hud.disable("intermissiontally")
	hud.disable("intermissionmessages")
	
	if player.realtime > player.starposttime
		player.starposttime = player.realtime
	end
	player.foesbeat = enemydestroyed
	player.ringsget = ringcollect
	player.ringcount = ringcount
	player.enemycount = enemycount
	
	if (drawtimebonus == nil)
		drawtimebonus = timebonus
	end
	
	if (drawringbonus == nil)
		drawringbonus = ringbonus
	end
	
	if (player.pflags & PF_FINISHED != 0 or player.exiting > 0)
		--stuff for emblems
		for emblem in mapthings.iterate
			if emblem.type == mobjinfo[MT_EMBLEM].doomednum
			and not modifiedgame
				if emblem.tag == GLOBAL_ZERO_SCORE_EMBLEM
				and player.score - player.spawnscore <= zeroerror
				and player.realtime <= tonumber(mapheaderinfo[gamemap].shscoretime) * TICRATE
				--and modeattacking == true
					P_SetOrigin(emblem.mobj, player.mo.x, player.mo.y, player.mo.z)
				end
			end
		end
		
		score = basescore + timebonus + ringbonus
		player.spawnscore = playerscore + score - basescore
		player.score = playerscore + score
		player.recordscore = score
		
	else
		score = 0
		timebonus = min(max((mapheaderinfo[gamemap].shtimebase +(60*mapheaderinfo[gamemap].shtimepenalty))-player.realtime/TICRATE*mapheaderinfo[gamemap].shtimepenalty,0), mapheaderinfo[gamemap].shtimebase)
		ringbonus = player.rings * 20
		drawtimebonus = timebonus
		drawringbonus = ringbonus
		basescore = player.score - player.spawnscore
		playerscore = player.spawnscore
	end
	--rework invulnerability
	if P_IsObjectOnGround(player.mo)
	or player.powers[pw_carry] == CR_ROLLOUT
		player.scoreadd = 0
	end
	
	--mid-level emblems
	if modifiedgame then return end
	for maxemblem in mapthings.iterate
		if maxemblem.type == mobjinfo[MT_EMBLEM].doomednum
			if maxemblem.tag == MAX_RINGS_EMBLEM
			and ringcollect >= tonumber(mapheaderinfo[gamemap].shrings)
			and ringcollect > 0
			and player.realtime <= tonumber(mapheaderinfo[gamemap].shringstime) * TICRATE
				P_SetOrigin(maxemblem.mobj, player.mo.x, player.mo.y, player.mo.z)
			end
			if maxemblem.tag == MAX_ENEMIES_EMBLEM
			and enemydestroyed >= tonumber(mapheaderinfo[gamemap].shenemies)
			and enemydestroyed > 0
			and player.realtime <= tonumber(mapheaderinfo[gamemap].shenemiestime) * TICRATE
				P_SetOrigin(maxemblem.mobj, player.mo.x, player.mo.y, player.mo.z)
			end
		end
	end
	
	--lum radar
	
	closestlum = nil
	closestdist = nil
	for lum in mapthings.iterate
		if lum.type == mobjinfo[MT_RAYMAN_YELLOWLUM].doomednum
		or lum.type == mobjinfo[MT_RAYMAN_WHITELUM].doomednum
			local dist = P_AproxDistance(P_AproxDistance(abs(player.mo.x - lum.mobj.x), abs(player.mo.y - lum.mobj.y)), abs(player.mo.z - lum.mobj.z)) / FRACUNIT
			if closestdist == nil
			or closestdist > dist
				if lum.mobj.health > 0
				and dist >= 0
					closestlum = lum.mobj
					closestdist = dist
				end
			end
		end
	end
	if closestlum == nil
		closestdist = nil
	end
	
	if modifiedgame then return end
	
	if (player.pflags & PF_FINISHED != 0 or player.exiting > 0)
		if fileupdateflag == 0
			file = io.openlocal(lumfile, "w")
			lumprogress = ""
			for i=1, maxlums do
				lumprogress = $ .. lumarray[i]
			end
			file:write(lumprogress)
			file:close()
			fileupdateflag = 1
		end
	end
	if lums >= maxlums
	and maxlums > 0
		for emblem in mapthings.iterate
			if emblem.type == mobjinfo[MT_EMBLEM].doomednum
				if emblem.tag == LUMS_EMBLEM
					P_SetOrigin(emblem.mobj, player.mo.x, player.mo.y, player.mo.z)
					if fileupdateflag == 0
						file = io.openlocal(lumfile, "w")
						lumprogress = ""
						for i=1, maxlums do
							lumprogress = $ .. lumarray[i]
						end
						file:write(lumprogress)
						file:close()
						fileupdateflag = 1
					end
				end
				if emblem.tag == LUMS_TIME_EMBLEM
				and lumattack >= maxlums
				and player.realtime <= tonumber(mapheaderinfo[gamemap].lumstime) * TICRATE
					P_SetOrigin(emblem.mobj, player.mo.x, player.mo.y, player.mo.z)
				end
			end
		end
	end
end)

--Load Lums
--Set zero error to 0 on map load
--count the rings and enemies in the level

addHook("MapLoad", function()
	if not mapheaderinfo[gamemap].lumslua then return end
	maxlums = 0
	currentlumid = 1
	zeroerror = 0
	ringcount = tonumber(mapheaderinfo[gamemap].shringerror)
	if ringcount == nil then ringcount = 0 end
	enemycount = 0
	ringcollect = 0
	enemydestroyed = 0
	for ring in mapthings.iterate
		if ring.mobj ~= nil
			if ring.mobj.ringvalue ~= nil
			and ring.mobj.ringvalue >= 0
				ringcount = $ + ring.mobj.ringvalue
			end
			if (ring.mobj.flags & MF_ENEMY)
				enemycount = $ + 1
			end
		end
	end
	for lum in mapthings.iterate
		if lum.type == mobjinfo[MT_RAYMAN_YELLOWLUM].doomednum
			maxlums = $ + 1
		end
	end
	for i=1, maxlums do
		lumarray[i] = 0
	end
	lums = 0
	fileupdateflag = 0
	lumfile = "client/lumdata/" + gamemap + ".dat"
	file = io.openlocal(lumfile, "r")
	if file == nil
		file = io.openlocal(lumfile, "w")
		file:write("")
	else
		lumprogress = file:read("*a")
	end
	file:close()
	for i=1, #lumprogress do
		local c = lumprogress:sub(i,i)
		if c == "1"
			lumarray[i] = 1
		end
	end
end)

--Netgame sync

addHook("NetVars", function(net)
	if not mapheaderinfo[gamemap].lumslua then return end
	lums = net($)
	lumattack = net($)
	enemydestroyed = net($)
	ringcollect = net($)
end)

--Add Lum to the table

addHook("TouchSpecial", function(special, toucher)
	if not mapheaderinfo[gamemap].lumslua then return end
	if toucher ~= nil
	and toucher.player ~= nil
	and toucher.player.bot == 0
		lumarray[special.lumid] = 1
		lums = $ + 1
		lumattack = $ + 1
	end
end, MT_RAYMAN_YELLOWLUM)

addHook("TouchSpecial", function(special, toucher)
	if not mapheaderinfo[gamemap].lumslua then return end
	if toucher ~= nil
	and toucher.player ~= nil
	and toucher.player.bot == 0
		lumattack = $ + 1
	end
end, MT_RAYMAN_WHITELUM)

--Remove collected lums on map retry

addHook("MapThingSpawn", function(mobj, mapthing)
	if not mapheaderinfo[gamemap].lumslua then return end
	currentlumid = 1 --change it later
	lums = 0
	lumattack = 0
end, MT_RAYMAN_YELLOWLUM)

addHook("MobjThinker", function(mobj)
	if mobj.valid
	and mobj.lumid == nil
		mobj.lumid = currentlumid
		currentlumid = $ + 1
	end
	for i=1, maxlums do
		if mobj.valid
		and lumarray[mobj.lumid] == 1
		and mobj.state >= S_RAYMAN_YELLOWLUM_1_1
		and mobj.state <= S_RAYMAN_YELLOWLUM_1_4
			P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_RAYMAN_WHITELUM)
			P_RemoveMobj(mobj)
			lums = $ + 1
		end
	end
end, MT_RAYMAN_YELLOWLUM)

--Empty Lum table on map change

addHook("MapChange", function(mapnum)
	if previousMap ~= gamemap
		previousMap = gamemap
	end
	if not mapheaderinfo[gamemap].lumslua then return end
	lums = 0
	lumattack = 0
	lumarray = {}
end)

--Draw hud

addHook("MapLoad", function(map)
	if mapheaderinfo[gamemap].lumslua
		hud.disable("score")
		hud.disable("time")
		hud.disable("rings")
		hud.disable("lives")
		hud.disable("intermissiontally")
		hud.disable("intermissionmessages")
	elseif previousMap ~= nil
	and mapheaderinfo[previousMap].lumslua
		hud.enable("intermissiontally")
		hud.enable("intermissionmessages")
		if mapheaderinfo[gamemap].lvlttl ~= "Hub"
			hud.enable("score")
			hud.enable("time")
			hud.enable("rings")
			hud.enable("lives")
		end
	end
end)

addHook("MobjDamage", function(mobj)
	if not mapheaderinfo[gamemap].lumslua then return end
	if mobj.player == nil then return end
	if mobj.player.bot ~= 0 then return end
	if mobj.player.powers[pw_shield] == 0
		mobj.rayhp = $ - 1
		if mobj.rayhp > 0
		and mobj.player.rings == 0
			mobj.player.powers[pw_shield] = SH_PITY
		end
		if mobj.rayhp == 0
		and mobj.player.rings > 0
			P_KillMobj(mobj)
		end
	end
end)

hud.add(function(v,player)
	if not mapheaderinfo[gamemap].lumslua then return end
	--icon
	v.draw(4+8, 4+12, v.getSprite2Patch(player.mo.skin, "LIFE"),  V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER, v.getColormap(player.mo.skin, player.mo.color))
	--health bar
	v.draw(24, 4, v.cachePatch("RAYMNHP" + player.mo.rayhp), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER)
	--air bar
	if player.powers[pw_underwater] > 0
	or player.powers[pw_spacetime] > 0
		v.draw(24, 12, v.cachePatch("RAYMNARE"), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER)
		local bar = 0
		local counter = 0
		if player.powers[pw_underwater] > 0
			bar = underwatertics
			counter = player.powers[pw_underwater]
		else
			bar = spacetimetics
			counter = player.powers[pw_spacetime]
		end
		for i = 0, counter * 60 / bar do
			v.draw(24 + i, 12, v.cachePatch("RAYMNARB"), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER)
		end
	end
	--score
	v.draw(4, 25, v.cachePatch("RAYHDSCO"), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER)
	--time
	v.draw(4, 38, v.cachePatch("RAYHDTIM"), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER)
	--rings
	v.draw(4, 51, v.cachePatch("RAYHDRN" .. ((player.realtime % 32) / 4) + 1), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER)
	--score
	intToHud(v, 112, 25, player.score - player.spawnscore, V_SNAPTOLEFT|V_SNAPTOTOP)
	--centiseconds
	intToHud(v, 112, 38, (player.realtime % TICRATE) * 100 / TICRATE, V_SNAPTOLEFT|V_SNAPTOTOP)
	if ((player.realtime % TICRATE) * 100 / TICRATE < 10)
		v.draw(100, 38, v.cachePatch("RAYHDNO0"), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER)
	end
	--point
	v.draw(88, 38, v.cachePatch("RAYHDDOT"), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER)
	--seconds
	intToHud(v, 76, 38, (player.realtime / TICRATE) % 60, V_SNAPTOLEFT|V_SNAPTOTOP)
	if (((player.realtime / TICRATE) % 60 )< 10)
		v.draw(64, 38, v.cachePatch("RAYHDNO0"), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER)
	end
	--colon
	v.draw(52, 38, v.cachePatch("RAYHDCOL"), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER)
	intToHud(v, 40, 38, player.realtime / (TICRATE * 60), V_SNAPTOLEFT|V_SNAPTOTOP)
	--rings
	intToHud(v, 112, 51, player.rings, V_SNAPTOLEFT|V_SNAPTOTOP)
	--hold scores button
	if (input.gameControlDown(GC_SCORES))
	or (input.gameControlDown(GC_CUSTOM3))
		--labels collectathon
		v.draw(4, 122, v.cachePatch("RAYHDLM" .. ((player.realtime % 12) / 4) + 1), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_PERPLAYER)
		v.draw(4, 150, v.cachePatch("RAYHDRN" .. ((player.realtime % 32) / 4) + 1), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_PERPLAYER)
		v.draw(4, 178, v.cachePatch("RAYHDFOE"), V_HUDTRANS|V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_PERPLAYER)
		--lums
		intToHud(v, 64, 115, lumattack, V_SNAPTOLEFT|V_SNAPTOBOTTOM)
		intToHud(v, 64, 128, lums, V_SNAPTOLEFT|V_SNAPTOBOTTOM)
		v.draw(76, 128, v.cachePatch("RAYHDSLA"), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_PERPLAYER)
		intToHud(v, 112, 128, maxlums, V_SNAPTOLEFT|V_SNAPTOBOTTOM)
		--rings
		intToHud(v, 52, 156, player.ringsget, V_SNAPTOLEFT|V_SNAPTOBOTTOM)
		v.draw(64, 156, v.cachePatch("RAYHDSLA"), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_PERPLAYER)
		intToHud(v, 112, 156, tonumber(mapheaderinfo[gamemap].shrings), V_SNAPTOLEFT|V_SNAPTOBOTTOM)
		intToHud(v, 112, 143, player.ringcount, V_SNAPTOLEFT|V_SNAPTOBOTTOM)
		--foes
		intToHud(v, 52, 184, player.foesbeat, V_SNAPTORIGHT|V_SNAPTOBOTTOM)
		v.draw(64, 184, v.cachePatch("RAYHDSLA"), V_HUDTRANS|V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_PERPLAYER)
		intToHud(v, 112, 184, tonumber(mapheaderinfo[gamemap].shenemies), V_SNAPTORIGHT|V_SNAPTOBOTTOM)
		intToHud(v, 112, 171, player.enemycount, V_SNAPTORIGHT|V_SNAPTOBOTTOM)
		--lum radar
		if closestdist ~= nil
			if closestdist < 128
				v.draw(152, 168, v.cachePatch("RAYLRDR6"), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_PERPLAYER)
				if player.realtime % 5 == 0
					S_StartSound(nil, sfx_emfind, player)
				end
			elseif closestdist < 512
				v.draw(152, 168, v.cachePatch("RAYLRDR5"), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_PERPLAYER)
				if player.realtime % 10 == 0
					S_StartSound(nil, sfx_emfind, player)
				end
			elseif closestdist < 1024
				v.draw(152, 168, v.cachePatch("RAYLRDR4"), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_PERPLAYER)
				if player.realtime % 20 == 0
					S_StartSound(nil, sfx_emfind, player)
				end
			elseif closestdist < 2048
				v.draw(152, 168, v.cachePatch("RAYLRDR3"), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_PERPLAYER)
				if player.realtime % 30 == 0
					S_StartSound(nil, sfx_emfind, player)
				end
			elseif closestdist < 3072
				v.draw(152, 168, v.cachePatch("RAYLRDR2"), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_PERPLAYER)
				if player.realtime % 35 == 0
					S_StartSound(nil, sfx_emfind, player)
				end
			else
				v.draw(152, 168, v.cachePatch("RAYLRDR1"), V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_PERPLAYER)
			end
		end
	end
end)

--Draw score bonus

hud.add(function(v,player)
	if not mapheaderinfo[gamemap].scorehaullua then return end
	//if (player.pflags & PF_FINISHED == 0 and player.exiting <= 0) then return end
	v.draw(215,5,v.cachePatch("YB_SCORE"),V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_PERPLAYER)
	v.drawNum(200,25,basescore,V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_PERPLAYER)
	v.draw(215,45,v.cachePatch("YB_TIME"),V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_PERPLAYER)
	v.drawNum(200,65,drawtimebonus,V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_PERPLAYER)
	v.draw(215,85,v.cachePatch("YB_RING"),V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_PERPLAYER)
	v.drawNum(200,105,drawringbonus,V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_PERPLAYER)
	v.draw(235,125,v.cachePatch("YB_TOTAL"),V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_PERPLAYER)
	v.drawNum(200,145,score,V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_PERPLAYER)
	if score >= tonumber(mapheaderinfo[gamemap].shs)
		v.draw(160,160,v.cachePatch("GRADE6"),V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_PERPLAYER)
	elseif score >= tonumber(mapheaderinfo[gamemap].sha)
		v.draw(160,160,v.cachePatch("GRADE5"),V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_PERPLAYER)
	elseif score >= tonumber(mapheaderinfo[gamemap].shb)
		v.draw(160,160,v.cachePatch("GRADE4"),V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_PERPLAYER)
	elseif score >= tonumber(mapheaderinfo[gamemap].shc)
		v.draw(160,160,v.cachePatch("GRADE3"),V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_PERPLAYER)
	elseif score >= tonumber(mapheaderinfo[gamemap].shd)
		v.draw(160,160,v.cachePatch("GRADE2"),V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_PERPLAYER)
	else
		v.draw(160,160,v.cachePatch("GRADE1"),V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_PERPLAYER)
	end
end, "intermission")

--make special emblems invisible

addHook("MobjThinker", function(mobj)
	if not mapheaderinfo[gamemap].scorehaullua then return end
	if (mobj.spawnpoint.tag > 9)
		mobj.state = S_INVISIBLE
	end
end, MT_EMBLEM)

--ring values for the counter

addHook("MobjSpawn", function(mobj)
	if not mapheaderinfo[gamemap].scorehaullua then return end
	mobj.ringvalue = doRingValue(1)
end, MT_RING)

addHook("MobjSpawn", function(mobj)
	if not mapheaderinfo[gamemap].scorehaullua then return end
	mobj.ringvalue = doRingValue(5)
end, MT_SOUTHDIST_RINGBOX5)

addHook("MobjSpawn", function(mobj)
	if not mapheaderinfo[gamemap].scorehaullua then return end
	mobj.ringvalue = doRingValue(10)
end, MT_RING_BOX)

addHook("MobjSpawn", function(mobj)
	if not mapheaderinfo[gamemap].scorehaullua then return end
	mobj.ringvalue = doRingValue(20)
end, MT_SOUTHDIST_RINGBOX20)

--Enemy scores, each enemy in combo adds 200 bonus points

for _, mt in ipairs{
    MT_RAYMAN_PIRATECRAWLA_GRAY, MT_RAYMAN_PIRATECRAWLA_GREEN,
    MT_POPHAT, MT_PENGUINATOR
} do
    addHook("MobjDeath", function(mobj, inflictor, player)
		if not mapheaderinfo[gamemap].scorehaullua then return end
		local scorebonustoadd = 200
		if mobj.type == MT_RAYMAN_PIRATECRAWLA_GRAY
		or mobj.type == MT_RAYMAN_PIRATECRAWLA_GREEN
			scorebonustoadd = mobj.info.mass
		end

		if (mobj.flags & MF_ENEMY)
			enemydestroyed = $ + 1
			if player ~= nil
			and player.player ~= nil
				if player.player.powers[pw_invulnerability] > 0
					scorebonustoadd = $ * 2
				end
				P_AddPlayerScore(player.player, player.player.scoreadd * 200 + scorebonustoadd)
				player.player.scoreadd = $ + 1
			else
				for player in players.iterate
					P_AddPlayerScore(player, scorebonustoadd)
				end
				zeroerror = $ + scorebonustoadd
			end
			mobj.state = mobj.info.deathstate
			return true
		end
		return false
    end, mt)
end

--Award points for vanilla rings and monitors

for _, mt in ipairs{
    MT_RING, MT_COIN,
	MT_RING_BOX,
	MT_RAYMAN_YELLOWLUM, MT_RAYMAN_WHITELUM,
	MT_PITY_BOX, MT_ATTRACT_BOX, MT_FORCE_BOX, MT_ARMAGEDDON_BOX, MT_WHIRLWIND_BOX, MT_ELEMENTAL_BOX,
	MT_SNEAKERS_BOX, MT_INVULN_BOX, MT_1UP_BOX,
	MT_FLAMEAURA_BOX, MT_BUBBLEWRAP_BOX, MT_THUNDERCOIN_BOX,
	MT_EMERHUNT,
	MT_SOUTHDIST_RINGBOX20, MT_SOUTHDIST_RINGBOX5
} do
    addHook("MobjDeath", function(mobj, inflictor, player)
		if not mapheaderinfo[gamemap].scorehaullua then return end
		if player == nil then return end
		if player.player == nil then return end
		if mobj.ringvalue ~= nil
			ringcollect = $ + mobj.ringvalue
		end
		local scorebonustoadd = 0
		if mobj.type == MT_RING
		or mobj.type == MT_COIN
			scorebonustoadd = 10
		elseif mobj.type == MT_RING_BOX
			scorebonustoadd = 100
		elseif mobj.type >= MT_PITY_BOX
		and mobj.type <= MT_1UP_BOX
		or mobj.type >= MT_FLAMEAURA_BOX
		and mobj.type <= MT_THUNDERCOIN_BOX
		or mobj.type == MT_SOUTHDIST_RINGBOX20
		or mobj.type == MT_RAYMAN_YELLOWLUM
		or mobj.type == MT_RAYMAN_WHITELUM
			scorebonustoadd = 200
		elseif mobj.type == MT_SOUTHDIST_RINGBOX5
			scorebonustoadd = 50
		elseif mobj.type == MT_EMERHUNT
			scorebonustoadd = 1000
			zeroerror = $ + 1000
		end
		if player.player.powers[pw_invulnerability] > 0
			scorebonustoadd = $ * 2
		end
		P_AddPlayerScore(player.player, scorebonustoadd)
    end, mt)
end